package com.topscomm.qem.util;

import com.aspose.words.Document;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfWriter;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.XmlCursor;
import org.springframework.util.CollectionUtils;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class GenerateWordTemplateUtil extends BaseTemplateUtil {
    public static void convertToPdf(String srcDocxPath, String destPdfPath) throws IOException {
        if (!getWordLicense()) { // 验证License 若不验证则转化出的pdf文档会有水印产生
            return;
        }
        try (FileOutputStream os = new FileOutputStream(destPdfPath);) {
            Document doc = new Document(srcDocxPath);
            doc.save(os, com.aspose.words.SaveFormat.PDF);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void convertImageToPdf(String srcPath, String destPdfPath) throws IOException {
        if (!getWordLicense()) { // 验证License 若不验证则转化出的pdf文档会有水印产生
            return;
        }
        FileOutputStream os = null;
        com.itextpdf.text.Document doc = null;
        try {
            File file = new File(destPdfPath); //新建一个pdf文档
            os = new FileOutputStream(file);
            doc = new com.itextpdf.text.Document(PageSize.A4, 20, 20, 20, 20);
            PdfWriter.getInstance(doc, os);
            doc.open();
            //获取图片的宽高
            Image image = Image.getInstance(srcPath);
            float imageHeight = image.getScaledHeight();
            float imageWidth = image.getScaledWidth();
            //设置页面宽高与图片一致
            Rectangle rectangle = new Rectangle(imageWidth, imageHeight);
            doc.setPageSize(rectangle);
            //图片居中
            image.setAlignment(Image.ALIGN_CENTER);
            //新建一页添加图片
            doc.newPage();
            doc.add(image);


        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
        	if(doc != null) {
        		doc.close();
        	}
            if (os != null) {
                os.close();
            }
        }
    }

    /**
     * 替换word文档中的文本
     * @param paraMap
     * @throws Exception
     */
    public static void replaceWordFile(Map<String, Object> paraMap, String sourcefilePath, String destFilePath, String fileName) throws Exception {
        File demoFile = new File(sourcefilePath);
        FileInputStream in = new FileInputStream(demoFile);
        XWPFDocument xwpf = new XWPFDocument(in);

        changeParagraphText(xwpf, paraMap);
        List<XWPFTable> tables = xwpf.getTables();
        changeContractTableText(xwpf, (List<Map<String, Object>>) paraMap.get("productList"), tables.get(0), true, paraMap);
        replaceTableText(paraMap, tables);

        OutputStream os = new FileOutputStream(destFilePath + "/" + fileName + ".docx");
        xwpf.write(os);
        closeStream(in);
        closeStream(os);
    }

    /**
     * @Description:    处理合同的特殊模板的表格
     * @Author:         mengmeng
     *                  withHead: true表示新生成的表格有表头， false表示没有表头
     * @Date:           2021/8/11 9:25
     * @Version:        1.0
     */
    public static void changeContractTableText(XWPFDocument document, List<Map<String, Object>> list, XWPFTable table, boolean withHead, Map<String, Object> paraMap) {
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        // 获取当前表格前面的paragraph
        int posOfTable = document.getPosOfTable(table);
        XWPFParagraph paragraphArray = document.getParagraphArray(posOfTable);

        // 在当前paragraph获得节点，创建一个新的table
        XmlCursor cursor = paragraphArray.getCTP().newCursor();
        XWPFTable newCreateTable = document.insertNewTbl(cursor);
        newCreateTable.getCTTbl().setTblPr(table.getCTTbl().getTblPr());

        if (withHead) {
            // 复制表头
            XWPFTableRow newCreateRow = newCreateTable.createRow();
            CopyTableRow(newCreateRow, table.getRow(0));// 复制行
        }

        for (int i = 0; i < list.size(); i++) {
            XWPFTableRow newCreateRow1 = newCreateTable.createRow();
            CopyTableRow(newCreateRow1, table.getRow(withHead ? 1 : 0));// 复制模板行
            replaceTableRow(newCreateRow1, list.get(i));// 处理标签替换
        }
        //处理尾行
        XWPFTableRow newCreateRow1 = newCreateTable.createRow();
        CopyTableRow(newCreateRow1, table.getRow(2));// 复制模板行
        replaceTableRow(newCreateRow1, paraMap);// 处理标签替换

        document.removeBodyElement(posOfTable);
        newCreateTable.removeRow(0);// 移除多出来的第一行
        document.createParagraph();// 添加回车换行
    }

    /**
     * 替换文档中段落文本
     *
     * @param document docx解析对象
     * @param textMap  需要替换的信息集合
     */
    public static void changeParagraphText(XWPFDocument document, Map<String, Object> textMap) {
        //替换页眉中的文字
        replaceHeaderText(textMap, document.getHeaderList());
        //替换段落文字
        replaceParagraphsText(textMap, document.getParagraphs());
        //替换页脚中的文字
        replaceFooterText(textMap, document.getFooterList());
    }

    /**
    * @Description:    替换页脚
    * @Author:         mengmeng
    * @Date:           2021/8/11 10:55
    * @Version:        1.0
    */
    public static void replaceFooterText(Map<String, Object> textMap, List<XWPFFooter> footerList) {
        if (CollectionUtils.isEmpty(footerList) || validateMap(textMap)) {
            return;
        }
        for (XWPFFooter xwpfFooter : footerList) {
            replaceTableAndParagraphText(textMap, xwpfFooter.getTables(), xwpfFooter.getParagraphs());
        }
    }

    /**
    * @Description:    替换页眉文字
    * @Author:         mengmeng
    * @Date:           2021/8/11 9:17
    * @Version:        1.0
    */
    public static void replaceHeaderText(Map<String, Object> textMap, List<XWPFHeader> headerList) {
        if (CollectionUtils.isEmpty(headerList) || validateMap(textMap)) {
            return;
        }
        for (XWPFHeader xwpfHeader : headerList) {
            replaceTableAndParagraphText(textMap, xwpfHeader.getTables(), xwpfHeader.getParagraphs());
        }
    }

    /**
    * @Description:    替换表格和paragraph中的文本
    * @Author:         mengmeng
    * @Date:           2021/8/11 10:59
    * @Version:        1.0
    */
    public static void replaceTableAndParagraphText(Map<String, Object> textMap, List<XWPFTable> tables, List<XWPFParagraph> paragraphs) {
        if (!CollectionUtils.isEmpty(tables)) {
            // 替换页眉表格
            replaceTableText(textMap, tables);
        }
        if (!CollectionUtils.isEmpty(paragraphs)) {
            // 替换页眉非表格，文本中的内容
            replaceParagraphsText(textMap, paragraphs);
        }
    }

    /**
    * @Description:    替换表格内容
    * @Author:         mengmeng
    * @Date:           2021/8/11 9:20
    * @Version:        1.0
    */
    public static void replaceTableText(Map<String, Object> textMap, List<XWPFTable> tables) {
        if (CollectionUtils.isEmpty(tables)) {
            return;
        }
        for (XWPFTable table : tables) {
            List<XWPFTableRow> rows = table.getRows();
            replaceRowsText(textMap, rows);
        }

    }

    /**
    * @Description:    替换表格行中内容
    * @Author:         mengmeng
    * @Date:           2021/8/11 9:23
    * @Version:        1.0
    */
    public static void replaceRowsText(Map<String, Object> textMap, List<XWPFTableRow> rows) {
        if (CollectionUtils.isEmpty(rows)) {
            return;
        }
        for (XWPFTableRow row : rows) {
            replaceTableRow(row, textMap);
        }
    }

    /**
    * @Description:    替换文本中的内容
    * @Author:         mengmeng
    * @Date:           2021/8/11 9:25
    * @Version:        1.0
    */
    public static void replaceParagraphsText(Map<String, Object> textMap, List<XWPFParagraph> paragraphs) {
        if (CollectionUtils.isEmpty(paragraphs) || validateMap(textMap)) {
            return;
        }
        for (XWPFParagraph paragraph : paragraphs) {
            replaceParagraphText(textMap, paragraph);
        }
    }

    public static void replaceParagraphText(Map<String, Object> textMap, XWPFParagraph paragraph) {
        //判断此段落时候需要进行替换
        String text = paragraph.getText();
        if (checkText(text)) {
            String regEx = "\\$\\{.+?\\}";
            Pattern pattern = Pattern.compile(regEx);
            Matcher matcher = pattern.matcher(text);
            if (matcher.find()) {
                replaceRunLabel(paragraph, textMap);
            }
        }
    }

    /**
    * @Description:    替换表格中的内容，该方法会删除掉文档中原来的表格，根据原文档中表格中的占位符，使用list列表中的数据替换，生成表格的行数会根据list的size决定
    * @Author:         mengmeng
    * @Date:           2021/8/11 9:25
    * @Version:        1.0
    */
    public static void changeTableText(XWPFDocument document, List<Map<String, Object>> list) {
//    	XWPFTable newCreateTable = document.createTable();// 创建新表格,默认一行一列

        List<XWPFTable> tables = document.getTables();
        changeTableText(document, list, tables.get(0), false);
    }

    /**
     * @Description:    替换表格中的内容，该方法会删除掉文档中原来的表格，根据原文档中表格中的占位符，使用list列表中的数据替换，生成表格的行数会根据list的size决定
     * @Author:         mengmeng
     *                  withHead: true表示新生成的表格有表头， false表示没有表头
     * @Date:           2021/8/11 9:25
     * @Version:        1.0
     */
    public static void changeTableText(XWPFDocument document, List<Map<String, Object>> list, XWPFTable table, boolean withHead) {
        // 获取当前表格前面的paragraph
        int posOfTable = document.getPosOfTable(table);
        XWPFParagraph paragraphArray = document.getParagraphArray(posOfTable);

        // 在当前paragraph获得节点，创建一个新的table
        XmlCursor cursor = paragraphArray.getCTP().newCursor();
        XWPFTable newCreateTable = document.insertNewTbl(cursor);
        newCreateTable.getCTTbl().setTblPr(table.getCTTbl().getTblPr());

        if (withHead) {
            // 复制表头
            XWPFTableRow newCreateRow = newCreateTable.createRow();
            CopyTableRow(newCreateRow, table.getRow(0));// 复制行
        }

        for (int i = 0; i < list.size(); i++) {
            XWPFTableRow newCreateRow1 = newCreateTable.createRow();
            CopyTableRow(newCreateRow1, table.getRow(withHead ? 1 : 0));// 复制模板行
            replaceTableRow(newCreateRow1, list.get(i));// 处理标签替换
        }

        document.removeBodyElement(posOfTable);
        newCreateTable.removeRow(0);// 移除多出来的第一行
        document.createParagraph();// 添加回车换行
    }

    public static void CopyTableRow(XWPFTableRow target, XWPFTableRow source) {

        int tempRowCellsize = source.getTableCells().size();// 模板行的列数
        for (int i = 0; i < tempRowCellsize - 1; i++) {
            target.addNewTableCell();// 为新添加的行添加与模板表格对应行行相同个数的单元格
        }
        // 复制样式
        target.getCtRow().setTrPr(source.getCtRow().getTrPr());
        // 复制单元格
        for (int i = 0; i < target.getTableCells().size(); i++) {
            copyTableCell(target.getCell(i), source.getCell(i));
        }
    }

    public static void copyTableCell(XWPFTableCell newTableCell, XWPFTableCell templateTableCell) {
        // 列属性
        newTableCell.getCTTc().setTcPr(templateTableCell.getCTTc().getTcPr());
        // 删除目标 targetCell 所有文本段落
        for (int pos = 0; pos < newTableCell.getParagraphs().size(); pos++) {
            newTableCell.removeParagraph(pos);
        }
        // 添加新文本段落
        for (XWPFParagraph sp : templateTableCell.getParagraphs()) {
            XWPFParagraph targetP = newTableCell.addParagraph();
            copyParagraph(targetP, sp);
        }
    }

    /**
    * @Description:    复制paragraph
    * @Author:         mengmeng
    * @Date:           2021/8/11 9:41
    * @Version:        1.0
    */
    public static void copyParagraph(XWPFParagraph newParagraph, XWPFParagraph templateParagraph) {
        // 设置段落样式
        newParagraph.getCTP().setPPr(templateParagraph.getCTP().getPPr());
        // 添加Run标签
        for (int pos = 0; pos < newParagraph.getRuns().size(); pos++) {
            newParagraph.removeRun(pos);

        }
        for (XWPFRun s : templateParagraph.getRuns()) {
            XWPFRun targetrun = newParagraph.createRun();
            CopyRun(targetrun, s);
        }

    }

    /**
    * @Description:    复制run
    * @Author:         mengmeng
    * @Date:           2021/8/11 9:42
    * @Version:        1.0
    */
    public static void CopyRun(XWPFRun newRun, XWPFRun templateRun) {
        newRun.getCTR().setRPr(templateRun.getCTR().getRPr());
        // 设置文本
        newRun.setText(templateRun.toString());

    }


    /**
     * @author MengM_
     * 替换run中的标签&{}
     */
    public static void replaceRunLabel(XWPFParagraph paragraph, Map<String, Object> textMap) {
        String regEx = "\\$\\{.+?\\}";
        Pattern pattern = Pattern.compile(regEx);
        Matcher matcher = pattern.matcher(paragraph.getText());
        if (!matcher.find()) {
            return;
        }

        int beginRunIndex = paragraph.searchText("$", new PositionInParagraph()).getBeginRun();// 标签开始run位置
        int endRunIndex = paragraph.searchText("}", new PositionInParagraph()).getEndRun();// 结束标签
        List<XWPFRun> runs = paragraph.getRuns();
        StringBuffer key = new StringBuffer();
        if (beginRunIndex == endRunIndex) { //买    方： ${customerCompany}    在同一行
            XWPFRun beginRun = runs.get(beginRunIndex);
            String beginRunText = beginRun.toString();
            int beginIndex = beginRunText.indexOf("$");
            int endIndex = beginRunText.indexOf("}");
            int length = beginRunText.length();

            if (beginIndex == 0 && endIndex == length - 1) {
                // 该run标签只有${**}
                XWPFRun insertNewRun = paragraph.insertNewRun(beginRunIndex);
                insertNewRun.getCTR().setRPr(beginRun.getCTR().getRPr());
                // 设置文本
                key.append(beginRunText.substring(2, endIndex));
                String valueBykey = getValueBykey(key.toString(), textMap);
                insertNewRun.setText(valueBykey);
                paragraph.removeRun(beginRunIndex + 1);
            } else {
                // 该run标签为**{**}** 或者 **{**} 或者{**}**，替换key后，还需要加上原始key前后的文本
                XWPFRun insertNewRun = paragraph.insertNewRun(beginRunIndex);
                insertNewRun.getCTR().setRPr(beginRun.getCTR().getRPr());
                // 设置文本
                key.append(beginRunText.substring(beginRunText.indexOf("{") + 1, beginRunText.indexOf("}")));
                String textString = beginRunText.substring(0, beginIndex) + getValueBykey(key.toString(), textMap)
                        + beginRunText.substring(endIndex + 1);
                insertNewRun.setText(textString);
                paragraph.removeRun(beginRunIndex + 1);
            }
        } else {//${}被分到多个run中


            //1、获取key值，（要替换的变量）
            int middleRunIndex = paragraph.searchText("{", new PositionInParagraph()).getBeginRun();// 左括号 { run位置
            ArrayList<Integer> removeRunList = new ArrayList<>();//需要移除的run
            if (middleRunIndex == -1) { // 只有$符号，没有 { 左括号
                return;
            }
            if (beginRunIndex == middleRunIndex) {// $和{ 在同一行

                //获取开始的run中的key值
                XWPFRun beginRun = runs.get(beginRunIndex);
                String beginRunText = beginRun.toString();
                int beginIndex = beginRunText.indexOf("{");
                int beginRunLength = beginRunText.length();
                if (beginRunLength > 2) {
                    key.append(beginRunText.substring(beginIndex + 1));
                }

                //处理中间的run
                for (int i = beginRunIndex + 1; i < endRunIndex; i++) {
                    removeRunList.add(i);
                    XWPFRun run = runs.get(i);
                    String runText = run.toString();
                    key.append(runText);
                }

                // 获取endRun中的key值
                XWPFRun endRun = runs.get(endRunIndex);
                String endRunText = endRun.toString();
                int endIndex = endRunText.indexOf("}");
                int endRunLeng = endRunText.length();
                if (endRunLeng > 1 && endIndex != 0) {//run中**}或者**}**
                    key.append(endRunText.substring(0, endIndex));
                }
            } else if (middleRunIndex == endRunIndex) {// { } 在同一行
                XWPFRun middleRun = runs.get(middleRunIndex);
                String middleRunText = middleRun.toString();
                int middleIndex = middleRunText.indexOf("{");
                int endIndex = middleRunText.indexOf("}");
                key.append(middleRunText.substring(middleIndex + 1, endIndex));
                //处理 $ 和 { 之间的run
                for (int i = beginRunIndex + 1; i < middleRunIndex; i++) {
                    removeRunList.add(i);
                }
            } else {// $和{ 不在同一行
                //获取开始的run中的key值
                XWPFRun middleRun = runs.get(middleRunIndex);
                String middleRunText = middleRun.toString();
                int middleIndex = middleRunText.indexOf("{");
                int middleRunLength = middleRunText.length();
                if (middleRunLength > 1) {
                    key.append(middleRunText.substring(middleIndex + 1));
                }

                //处理 $ 和 { 之间的run
                for (int i = beginRunIndex + 1; i < middleRunIndex; i++) {
                    removeRunList.add(i);
                }

                //处理中间的run
                for (int i = middleRunIndex + 1; i < endRunIndex; i++) {
                    removeRunList.add(i);
                    XWPFRun run = runs.get(i);
                    String runText = run.toString();
                    key.append(runText);
                }

                // 获取endRun中的key值
                XWPFRun endRun = runs.get(endRunIndex);
                String endRunText = endRun.toString();
                int endIndex = endRunText.indexOf("}");
                int endRunLeng = endRunText.length();
                if (endRunLeng > 1 && endIndex != 0) {//run中**}或者**}**
                    key.append(endRunText.substring(0, endIndex));
                }
            }


            //*******************************************************************
            //取得key值后替换标签
            String valueBykey = getValueBykey(key.toString(), textMap);
            if (beginRunIndex == middleRunIndex) {// $和{ 在同一行

                //先处理 $和{所在行
                XWPFRun beginRun = runs.get(beginRunIndex);
                String beginRunText = beginRun.toString();
                int beginIndex = beginRunText.indexOf("$");
                if (beginIndex == 0 && beginRunText.length() == 2) { // 该run只有 ${
                    // run标签内文本{
                    XWPFRun insertNewRun = paragraph.insertNewRun(beginRunIndex);
                    insertNewRun.getCTR().setRPr(beginRun.getCTR().getRPr());
                    // 设置文本
                    insertNewRun.setText(valueBykey);
                    paragraph.removeRun(beginRunIndex + 1);//移除原始的run
                } else {
                    // 该run标签为**${**或者 ${** ，替换key后，还需要加上原始key前的文本
                    XWPFRun insertNewRun = paragraph.insertNewRun(beginRunIndex);
                    insertNewRun.getCTR().setRPr(beginRun.getCTR().getRPr());
                    // 设置文本
                    String textString = beginRunText.substring(0, beginRunText.indexOf("$")) + valueBykey;
                    insertNewRun.setText(textString);
                    paragraph.removeRun(beginRunIndex + 1);//移除原始的run
                }

                //再处理 } 所在run
                XWPFRun endRun = runs.get(endRunIndex);
                String endRunText = endRun.toString();
                int endIndex = endRunText.indexOf("}");
                int endRunLeng = endRunText.length();
                if (endRunText.length() == 1) {
                    // run标签内文本只有}
                    XWPFRun insertNewRun = paragraph.insertNewRun(endRunIndex);
                    insertNewRun.getCTR().setRPr(endRun.getCTR().getRPr());
                    // 设置文本
                    insertNewRun.setText("");
                    paragraph.removeRun(endRunIndex + 1);//移除原始的run

                } else {
                    // 该run标签为**}**或者 }** 或者**}，替换key后，还需要加上原始key后的文本
                    XWPFRun insertNewRun = paragraph.insertNewRun(endRunIndex);
                    insertNewRun.getCTR().setRPr(endRun.getCTR().getRPr());
                    // 设置文本
                    String textString = endRunText.substring(endRunText.indexOf("}") + 1);
                    insertNewRun.setText(textString);
                    paragraph.removeRun(endRunIndex + 1);//移除原始的run
                }

            } else if (middleRunIndex == endRunIndex) {// { } 在同一行
                //先处理$所在run
                XWPFRun beginRun = runs.get(beginRunIndex);
                String beginRunText = beginRun.toString();
                int beginIndex = beginRunText.indexOf("$");
                if (beginIndex == 0 && beginRunText.length() == 1) { // 该run只有 ${
                    // run标签内文本{
                    XWPFRun insertNewRun = paragraph.insertNewRun(beginRunIndex);
                    insertNewRun.getCTR().setRPr(beginRun.getCTR().getRPr());
                    // 设置文本
                    insertNewRun.setText("");
                    paragraph.removeRun(beginRunIndex + 1);//移除原始的run
                } else {
                    // 该run标签为**$ ，替换后，还需要加上原始key前的文本
                    XWPFRun insertNewRun = paragraph.insertNewRun(beginRunIndex);
                    insertNewRun.getCTR().setRPr(beginRun.getCTR().getRPr());
                    // 设置文本
                    String textString = beginRunText.substring(0, beginRunText.indexOf("$"));
                    insertNewRun.setText(textString);
                    paragraph.removeRun(beginRunIndex + 1);//移除原始的run
                }

                //处理 { }所在的run
                XWPFRun middleRun = runs.get(middleRunIndex);
                String middleRunText = middleRun.toString();
                int middleIndex = middleRunText.indexOf("{");
                int endIndex = middleRunText.indexOf("}");
                if (middleIndex == 0 && endIndex == middleRunText.length() - 1) {//该 run只有  {**}
                    XWPFRun insertNewRun = paragraph.insertNewRun(middleRunIndex);
                    insertNewRun.getCTR().setRPr(middleRun.getCTR().getRPr());
                    // 设置文本
                    insertNewRun.setText(valueBykey);
                    paragraph.removeRun(middleRunIndex + 1);//移除原始的run
                } else {//  该run是 {**}***

                    XWPFRun insertNewRun = paragraph.insertNewRun(middleRunIndex);
                    insertNewRun.getCTR().setRPr(middleRun.getCTR().getRPr());
                    // 设置文本
                    String textString = middleRunText.substring(middleRunText.indexOf("}") + 1);
                    insertNewRun.setText(valueBykey + textString);
                    paragraph.removeRun(middleRunIndex + 1);//移除原始的run
                }


            } else {// $和{和 }都在不同run

                //先处理 $ 所在run
                XWPFRun beginRun = runs.get(beginRunIndex);
                String beginRunText = beginRun.toString();
                int beginIndex = beginRunText.indexOf("$");
                if (beginRunText.length() == 0 && beginIndex == 0) {// 该run只有 ${
                    // run标签内文本{
                    XWPFRun insertNewRun = paragraph.insertNewRun(beginRunIndex);
                    insertNewRun.getCTR().setRPr(beginRun.getCTR().getRPr());
                    // 设置文本
                    insertNewRun.setText("");
                    paragraph.removeRun(beginRunIndex + 1);//移除原始的run
                } else {
                    // 该run标签为**$ ，替换后，还需要加上原始key前的文本
                    XWPFRun insertNewRun = paragraph.insertNewRun(beginRunIndex);
                    insertNewRun.getCTR().setRPr(beginRun.getCTR().getRPr());
                    // 设置文本
                    String textString = beginRunText.substring(0, beginRunText.indexOf("$"));
                    insertNewRun.setText(textString);
                    paragraph.removeRun(beginRunIndex + 1);//移除原始的run
                }

                //再处理 { 所在 run
                XWPFRun middleRun = runs.get(middleRunIndex);
                String middleRunText = middleRun.toString();
                int middleIndex = middleRunText.indexOf("{");
                XWPFRun insertNewRun = paragraph.insertNewRun(middleRunIndex);
                insertNewRun.getCTR().setRPr(middleRun.getCTR().getRPr());
                // 设置文本
                insertNewRun.setText(valueBykey);
                paragraph.removeRun(middleRunIndex + 1);//移除原始的run

                //最后处理 } 所在run
                XWPFRun endRun = runs.get(endRunIndex);
                String endRunText = endRun.toString();
                int endIndex = endRunText.indexOf("}");
                int endRunLeng = endRunText.length();
                if (endRunText.length() == 1) {
                    // run标签内文本只有}
                    XWPFRun insertNewRun1 = paragraph.insertNewRun(endRunIndex);
                    insertNewRun.getCTR().setRPr(endRun.getCTR().getRPr());
                    // 设置文本
                    insertNewRun1.setText("");
                    paragraph.removeRun(endRunIndex + 1);//移除原始的run

                } else {
                    // 该run标签为**}**或者 }** 或者**}，替换key后，还需要加上原始key后的文本
                    XWPFRun insertNewRun1 = paragraph.insertNewRun(endRunIndex);
                    insertNewRun.getCTR().setRPr(endRun.getCTR().getRPr());
                    // 设置文本
                    String textString = endRunText.substring(endRunText.indexOf("}") + 1);
                    insertNewRun1.setText(textString);
                    paragraph.removeRun(endRunIndex + 1);//移除原始的run
                }

            }

            //处理中间的run标签
            for (int i = 0; i < removeRunList.size(); i++) {
                XWPFRun xWPFRun = runs.get(removeRunList.get(i));//原始run
                XWPFRun insertNewRun = paragraph.insertNewRun(removeRunList.get(i));
                insertNewRun.getCTR().setRPr(xWPFRun.getCTR().getRPr());
                insertNewRun.setText("");
                paragraph.removeRun(removeRunList.get(i) + 1);//移除原始的run
            }
        }
        //处理一个run中有多个变量需要替换
        replaceRunLabel(paragraph, textMap);
    }

    /**
    * @Description:    根据key获取value值
    * @Author:         mengmeng
    * @Date:           2021/8/11 9:43
    * @Version:        1.0
    */
    public static String getValueBykey(String key, Map<String, Object> map) {
        String returnValue = "";
        if (key != null) {
            try {
                returnValue = map.get(key) != null ? map.get(key).toString() : "";
            } catch (Exception e) {
                System.out.println("key:" + key + "***" + e);
                returnValue = "";
            }

        }
        return returnValue;
    }



    /**
     * 判断文本中时候包含$
     *
     * @param text 文本
     * @return 包含返回true, 不包含返回false
     */
    public static boolean checkText(String text) {
        boolean check = false;
        if (text.indexOf("${") != -1) {
            check = true;
        }
        return check;
    }


    /**
     * 关闭输入流
     *
     * @param is
     */
    public static void closeStream(InputStream is) {
        if (is != null) {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 关闭输出流
     *
     * @param is
     */
    public static void closeStream(OutputStream is) {
        if (is != null) {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    /**
    * @Description:    对表格单行进行标签替换
    * @Author:         mengmeng
    * @Date:           2021/8/11 9:21
    * @Version:        1.0
    */
    public static void replaceTableRow(XWPFTableRow tableRow, Map<String, Object> parametersMap) {
        if (null == tableRow || parametersMap == null) {
            return;
        }
        List<XWPFTableCell> tableCells = tableRow.getTableCells();
        replaceTableCell(parametersMap, tableCells);

    }

    /**
    * @Description:    替换表格单元格
    * @Author:         mengmeng
    * @Date:           2021/8/11 9:46
    * @Version:        1.0
    */
    public static void replaceTableCell(Map<String, Object> parametersMap, List<XWPFTableCell> tableCells) {
        if (CollectionUtils.isEmpty(tableCells) || validateMap(parametersMap)) {
            return;
        }
        for (XWPFTableCell xWPFTableCell : tableCells) {
            List<XWPFParagraph> paragraphs = xWPFTableCell.getParagraphs();
            replaceParagraphsText(parametersMap, paragraphs);
        }
    }



    /**
     * 对表格内的标签进行替换
     *
     * @param xwpfTable
     * @param parametersMap
     */
    public static void replaceTable(XWPFTable xwpfTable, Map<String, Object> parametersMap) {
        List<XWPFTableRow> rows = xwpfTable.getRows();
        for (XWPFTableRow xWPFTableRow : rows) {
            List<XWPFTableCell> tableCells = xWPFTableRow.getTableCells();
            replaceTableCell(parametersMap, tableCells);
        }

    }

    /**
    * @Description:    校验入参
    * @Author:         mengmeng
    * @Date:           2021/8/11 9:50
    * @Version:        1.0
    */
    public static boolean validateMap(Map<String, Object> map) {
        if (null == map) {
            return false;
        }
        return map.isEmpty();
    }


}
